import type { ILatestThemeMeta } from '../../../../lib/abstract/page_manager'
import type {
  BaseStyleConfig,
  IPersonalizationItemConfig,
  PlatformTypeValue,
} from '../../../../types/interfaces'
import { Select } from '../../../../components/select'
import { UserPref } from '../../../../lib/abstract'
import { ToolKit } from '../../../../lib/utils/toolkit'
import { ConfigManager } from '../../../../module/config_manager'
import { AppModule } from '../../../../module/config_manager/types'
import {
  GM_STORAGE_KEYS,
  HOSTNAME,
  LOCAL_STORAGE_KEYS,
  logger,
  SUPPORTED_PLATFORMS,
  ThemeSettingsManager,
  VALID_RESULT,
} from '../../../../types/constants'
import {
  SYMBOLS,
  ThemeSourceMode,
  ThemeType,
} from '../../../../types/interfaces'
import { getThemeOptions } from '../custom_css/theme'
import { PageThemeService } from './service'
import { StyleOperateType } from './types'

export class PageTheme extends UserPref {
  readonly id = 'page_theme'
  readonly name = 'PageTheme'
  readonly themeMetaSupportedPlatforms: PlatformTypeValue[] | '*' = '*'
  readonly styleConfigKey = 'pageTheme'
  readonly cssProperty = ''
  readonly cssValueSuffix = ''

  // 启用页面类型隔离
  usePageTypeIsolation = true
  readonly notSupportedPlatforms: PlatformTypeValue[] = [
    SUPPORTED_PLATFORMS.GITEE,
    SUPPORTED_PLATFORMS.GITHUB,
  ]

  private readonly configManager: ConfigManager = ConfigManager.getInstance()

  // 主题服务
  private readonly service: PageThemeService = PageThemeService.getInstance()
  private titleStylesApplied = false
  private latestThemeMeta: ILatestThemeMeta | undefined
  private autoUpdateTheme = false

  constructor(config: IPersonalizationItemConfig) {
    super(config)

    this.service.init()
  }

  /**
   * 创建实例的工厂方法（替代直接使用构造函数）
   */
  static async create(config: IPersonalizationItemConfig): Promise<PageTheme> {
    const instance = new PageTheme(config)

    if (instance.isEnableModule())
      await instance.initLatestThemeMeta()

    return instance
  }

  /**
   * 主题元数据是否启用
   */
  isEnableThemeMeta(): boolean {
    return (this.themeMetaSupportedPlatforms === '*' || this.themeMetaSupportedPlatforms.includes(HOSTNAME))
      && this.configManager.getFeatureEnabled(AppModule.ThemeInherit.id, false)
  }

  /**
   * 初始化最新主题元数据
   */
  private async initLatestThemeMeta(): Promise<void> {
    if (!this.isEnableThemeMeta())
      return

    this.pollingHandler.api.awaitCondition(
      () => !!this.storageGet(GM_STORAGE_KEYS.latestThemeMeta, undefined),
      () => {
        this.latestThemeMeta = this.storageGet(GM_STORAGE_KEYS.latestThemeMeta, undefined)
        logger.attention(`[${this.name}] 最新主题元数据记录结果`, this.latestThemeMeta)
      },
    )

    this.initialize() // 确保属性已初始化
  }

  createComponent(config: BaseStyleConfig, value: string, _mode: string, debouncedSave: (() => void) & { flush: () => void }): Select {
    const theme = this.getApplyTheme(value as ThemeType)
    const id = this.generateId(config.styleVar)
    const remark = config.remark || ''

    this.cachedValues.set(id, theme)

    return new Select({
      id,
      selectedValue: theme,
      label: '网页主题',
      labelTextPosition: 'left',
      options: getThemeOptions(),
      clearable: true,
      showPlaceholder: true,
      placeholder: '选择主题',
      title: remark,
      onInit: (instance) => {
        let isSynced = false

        // 主题继承
        if (this.isUpdateTheme()) {
          this.autoUpdateTheme = true

          let inheritTheme: ThemeType

          if (theme !== ThemeType.LIGHT) {
            inheritTheme = theme
            isSynced = true
          }
          else {
            inheritTheme = this.latestThemeMeta!.theme
          }

          instance.setValue(inheritTheme)
          logger.attention(`[${this.name}] 继承 ${inheritTheme} 主题`)
        }

        // 主题同步
        if (!isSynced && value && theme !== value) {
          instance.setValue(theme)
        }
      },
      onChange: (value: string | undefined) => {
        this.cachedValues.set(id, value || '')
        debouncedSave()
        this.handleSelectChange(value)
      },
    })
  }

  /**
   * 获取当前主题
   */
  private getApplyTheme(value: ThemeType): ThemeType {
    return this.configManager.getFeatureEnabled(AppModule.ThemeSync.id) ? ToolKit.browser.theme.getCurrentTheme() : value
  }

  /**
   * 检查是否更新主题
   */
  isUpdateTheme(): boolean {
    return !!this.latestThemeMeta && this.latestThemeMeta?.enabled && this.latestThemeMeta?.styleOperateType === StyleOperateType.Update
  }

  isChanged(newValue: string, oldValue: string): boolean {
    if (this.autoUpdateTheme) {
      this.autoUpdateTheme = false
      return false
    }

    return newValue !== oldValue
  }

  handleSelectChange(value: string | undefined): void {
    if (value) {
      logger.important(`[${this.name}] ${SYMBOLS.OTHERS.PALETTE} 主题切换为: ${value}`)
    }
    else {
      logger.important(`[${this.name}] ${SYMBOLS.OTHERS.CLEAR} 移除主题样式`)
    }

    ToolKit.browser.theme.setTheme(value ? (value as ThemeType) : ThemeType.LIGHT)

    this.service.registerStyles(value as ThemeType)
    this.service.applyTitleStyles(value || '')
    this.titleStylesApplied = true
  }

  afterSetStorageValues(value: string): void {
    // 同步加载主题到本地存储中

    // 页面主题配置
    ThemeSettingsManager.set({
      [this.pageType]: {
        theme: value as ThemeType,
        update_time: new Date().toLocaleString(),
      },
    })

    // 平台最新主题
    localStorage.setItem(LOCAL_STORAGE_KEYS.PageTheme, value)
  }

  // 由于直接使用的是 select 传递的值，所以不需要额外的校验逻辑（支持为空）
  handleCheck(_value: string): { status: ValidResultType, error: string } {
    return { status: VALID_RESULT.VALID.value, error: '' }
  }

  applyStyles(): void {
    this.getInstanceIds().forEach((id) => {
      const value = this.cachedValues.get(id) as string

      if (!this.titleStylesApplied)
        this.service.applyTitleStyles(value)

      this.service.registerStyles((value || ThemeType.LIGHT) as ThemeType)
    })

    // 根据样式变量更新主题
    if (!this.configManager.getFeatureEnabled(AppModule.ThemeSync.id)) {
      ToolKit.browser.theme.setTheme(ToolKit.browser.theme.getCurrentTheme(ThemeSourceMode.COMPUTED))
    }
  }
}
